package com.activiti.flow.service.Impl;

import com.activiti.basic.exception.BusinessException;
import com.activiti.flow.constant.ModelConstant;
import com.activiti.flow.model.vo.ModelVo;
import com.activiti.flow.service.ModelService;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author pisory
 * @version 1.0
 * @date 2020/4/5
 */
@Service
public class ModelServiceImpl implements ModelService {
    @Autowired
    RepositoryService repositoryService;

    @Autowired
    ObjectMapper objectMapper;

    @Override
    public Model createModel(ModelVo vo) throws Exception{
        //初始化一个空模型
        Model model = repositoryService.newModel();

        //设置模型信息
        model.setName(vo.getName());
        model.setKey(StringUtils.defaultString(vo.getKey()));
        model.setCategory(vo.getCategory());

        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME, vo.getName());
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, vo.getDescription());
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, vo.getRevision());
        modelNode.put(ModelConstant.MODEL_CONTENT, vo.getContent());
        model.setMetaInfo(modelNode.toString());

        repositoryService.saveModel(model);
        String id = model.getId();

        //完善模型界面资源EditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
        return model;
    }

    @Override
    public Model updateModel(ModelVo vo) throws Exception {
        return null;
    }

    @Override
    public Model deployModel(String modelId) throws Exception {
        //获取模型
        Model modelData = repositoryService.getModel(modelId);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());

        if (bytes == null) {
            throw new BusinessException("模型数据为空，请先设计流程并成功保存，再进行发布。");
        }

        JsonNode modelNode = new ObjectMapper().readTree(bytes);

        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if (model.getProcesses().size() == 0) {
            throw new BusinessException("数据模型不符要求，请至少设计一条主线流程。");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

        //发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .addString(processName, new String(bpmnBytes, "UTF-8"))
                .deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);
        return null;
    }
}
